/* pmsg_create.c

   Create a POSIX message queue.

   Usage as shown in usageError().

   Linux supports POSIX message queues since kernel 2.6.6.
*/
#include <fcntl.h>
#include <getopt.h>
#include <mqueue.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <unistd.h>

static void errExit(char *msg) {
  perror(msg);
  exit(EXIT_FAILURE);
}

static void usageError(const char *progName) {
  fprintf(stderr,
          "Usage: %s [-cx] [-m maxmsg] [-s msgsize] mq-name "
          "[octal-perms]\n",
          progName);
  fprintf(stderr, "    -c          Create queue (O_CREAT)\n");
  fprintf(stderr, "    -m maxmsg   Set maximum # of messages\n");
  fprintf(stderr, "    -s msgsize  Set maximum message size\n");
  fprintf(stderr, "    -x          Create exclusively (O_EXCL)\n");
  exit(EXIT_FAILURE);
}

int main(int argc, char *argv[]) {
  int flags, opt;
  mode_t perms;
  mqd_t mqd;
  struct mq_attr attr, *attrp;

  /* If 'attrp' is NULL, mq_open() uses default attributes. If an
     option specifying a message queue attribute is supplied on the
     command line, we save the attribute in 'attr' and set 'attrp'
     pointing to 'attr'. We assign some (arbitrary) default values
     to the fields of 'attr' in case the user specifies the value
     for one of the queue attributes, but not the other. */
  attrp = NULL;
  attr.mq_maxmsg = 10;
  attr.mq_msgsize = 2048;
  flags = O_RDWR;

  /* Parse command-line options */
  while ((opt = getopt(argc, argv, "cm:s:x")) != -1) {
    switch (opt) {
      case 'c':
        flags |= O_CREAT;
        break;

      case 'm':
        attr.mq_maxmsg = atoi(optarg);
        attrp = &attr;
        break;

      case 's':
        attr.mq_msgsize = atoi(optarg);
        attrp = &attr;
        break;

      case 'x':
        flags |= O_EXCL;
        break;

      default:
        usageError(argv[0]);
    }
  }

  if (optind >= argc) usageError(argv[0]);

  perms = (argc <= optind + 1) ? (S_IRUSR | S_IWUSR) : atoi(argv[optind + 1]);

  mqd = mq_open(argv[optind], flags, perms, attrp);
  if (mqd == (mqd_t)-1) errExit("mq_open");

  exit(EXIT_SUCCESS);
}